Skip to content

[JULES] Refactor text stdlib to use generic helpers - #354

Closed
logbie wants to merge 1 commit into
mainfrom
jules-refactor-text-stdlib-helpers-10726499022893340770
Closed

[JULES] Refactor text stdlib to use generic helpers#354
logbie wants to merge 1 commit into
mainfrom
jules-refactor-text-stdlib-helpers-10726499022893340770

Conversation

@logbie

@logbie logbie commented Feb 17, 2026

Copy link
Copy Markdown
Collaborator

Refactored src/stdlib/text.rs to use generic helpers in src/stdlib/helpers.rs (unary_text_op and binary_text_predicate) to reduce code duplication and improve maintainability. Verified with full test suite.


PR created automatically by Jules for task 10726499022893340770 started by @logbie

Summary by CodeRabbit

  • Bug Fixes
    • Improved text capitalization function to correctly handle empty strings.

This commit introduces `unary_text_op` and `binary_text_predicate` to `src/stdlib/helpers.rs` and refactors `src/stdlib/text.rs` to use these helpers. This reduces code duplication for common text operations like `touppercase`, `tolowercase`, `trim`, `capitalize`, `reverse_text`, `starts_with`, and `ends_with`.

The `trim` function now allocates an intermediate `String` to fit the generic helper signature, prioritizing maintainability and consistency over micro-optimization in this context.

Verified with `cargo fmt`, `cargo clippy`, and `cargo test`.

Co-authored-by: logbie <1138960+logbie@users.noreply.github.com>
@google-labs-jules

Copy link
Copy Markdown
Contributor

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

Copilot AI review requested due to automatic review settings February 17, 2026 10:13
@claude

claude Bot commented Feb 17, 2026

Copy link
Copy Markdown
Contributor

Claude finished @logbie's task —— View job


PR Review: Refactor text stdlib to use generic helpers

Review Tasks

  • Read and analyze src/stdlib/helpers.rs changes
  • Read and analyze src/stdlib/text.rs refactoring
  • Check code quality and best practices
  • Look for potential bugs or issues
  • Assess performance implications
  • Review security considerations
  • Evaluate test coverage impact
  • Provide comprehensive feedback

Summary

This PR successfully refactors the text stdlib functions to use generic helper functions, reducing code duplication from 44 lines to 18 lines while maintaining identical functionality. The refactoring is well-executed and follows good software engineering principles.

✅ Positives

Excellent Code Reduction and DRY Principles

  • 44 lines removed, 18 lines added: Net reduction of 26 lines while adding 2 new helper functions
  • Eliminates repetitive boilerplate in 6 text functions: touppercase, tolowercase, trim, starts_with, ends_with, capitalize, and reverse_text
  • Each function now condensed to a single, clear line using the appropriate helper

Well-Designed Generic Helpers

  • unary_text_op: Perfect abstraction for Text→Text transformations (src/stdlib/helpers.rs:487-494)
  • binary_text_predicate: Clean abstraction for Text×Text→Bool operations (src/stdlib/helpers.rs:506-518)
  • Both helpers follow the established pattern of existing unary_math_op and binary_math_op functions

Maintains Full Functionality

  • All argument validation, type checking, and error handling preserved
  • Error messages remain consistent and informative
  • Memory management with Arc<str> unchanged
  • All existing unit tests should pass without modification

Code Quality

  • Comprehensive documentation for both new helper functions
  • Consistent naming and patterns with existing helpers
  • Proper use of generic bounds: F: Fn(&str) -> String and F: Fn(&str, &str) -> bool

⚠️ Minor Observations

Inconsistent Usage of Arc vs Rc

The expect_text function returns Arc<str> but the docstring mentions Rc<str>. While the code is correct, the documentation should be updated:

// helpers.rs:248-249 - Documentation mentions Rc but returns Arc
/// Returns an `Rc<str>` to enable efficient memory sharing without copying
pub fn expect_text(value: &Value) -> Result<Arc<str>, RuntimeError> {

This is a pre-existing documentation issue, not caused by this refactoring.

Potential Helper Extension

While not required for this PR, the pattern could be extended to other text functions like replace() which currently has manual implementation but could benefit from a ternary_text_op helper.

🔒 Security & Performance

  • Memory Safety: Proper use of reference-counted strings maintains memory safety
  • Performance: No performance regression - same operations, just refactored
  • Resource Management: No changes to resource usage patterns

🧪 Test Coverage

The existing comprehensive unit tests in src/stdlib/text.rs:370-521 will continue to validate all refactored functions:

  • Edge cases (empty strings, unicode)
  • Error conditions (argument count validation)
  • Boundary conditions (padding limits, negative values)

📊 Impact Assessment

Aspect Impact Notes
Functionality ✅ None Identical behavior maintained
Performance ✅ Neutral Same operations, cleaner code
Maintainability 🟢 Positive Reduced duplication, clearer intent
Test Coverage ✅ Maintained All existing tests remain valid
Breaking Changes ✅ None Public API unchanged

🎯 Recommendation

✅ APPROVED - This is an excellent refactoring that improves code maintainability while preserving all functionality. The implementation demonstrates good software engineering practices with proper abstraction and documentation.

The only suggestion is to fix the documentation inconsistency in expect_text() (Arc vs Rc), but this is a pre-existing issue not introduced by this PR.


@coderabbitai

coderabbitai Bot commented Feb 17, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

The changes introduce two new public helper functions (unary_text_op and binary_text_predicate) in helpers.rs for standardized text argument validation and operation execution. Multiple text functions in text.rs are refactored to replace repetitive validation and extraction logic with calls to these helpers, reducing code duplication.

Changes

Cohort / File(s) Summary
Helper Function Utilities
src/stdlib/helpers.rs
Added two new public helper functions: unary_text_op for single-argument text operations returning Text values, and binary_text_predicate for two-argument text comparisons returning Bool values. Both include comprehensive doc comments.
Text Function Refactoring
src/stdlib/text.rs
Refactored seven native text functions (native_touppercase, native_tolowercase, native_trim, native_starts_with, native_ends_with, native_capitalize, native_reverse_text) to use the new unary_text_op or binary_text_predicate helpers, eliminating explicit argument counting and text extraction boilerplate.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 Hoppy helpers hop about,
Text ops clean, without a doubt,
No more duplication's blight,
One plus two, made just right!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main change: refactoring the text stdlib module to use generic helper functions, which is exactly what the changeset accomplishes.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch jules-refactor-text-stdlib-helpers-10726499022893340770

Tip

Issue Planner is now in beta. Read the docs and try it out! Share your feedback on Discord.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Refactors text stdlib functions to use generic helper functions, reducing duplication and centralizing common argument/type handling.

Changes:

  • Introduced unary_text_op and binary_text_predicate helpers in src/stdlib/helpers.rs.
  • Updated several text stdlib natives (touppercase, tolowercase, trim, starts_with, ends_with, capitalize, reverse) to use the new helpers.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
src/stdlib/text.rs Replaces repeated arg/type handling with calls to new generic text helpers.
src/stdlib/helpers.rs Adds reusable helper functions for unary text transforms and binary text predicates.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/stdlib/text.rs
let text = expect_text(&args[0])?;
let trimmed = text.trim();
Ok(Value::Text(Arc::from(trimmed)))
unary_text_op("trim", args, |s| s.trim().to_string())

Copilot AI Feb 17, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

trim previously could avoid constructing an intermediate String by directly converting the trimmed &str into Arc<str>. With unary_text_op requiring Fn(&str) -> String, trim() now always allocates a String, which is avoidable for slice-based transforms. Consider adjusting unary_text_op to accept something like Cow<'_, str> (borrow for trim, own for to_uppercase/etc.), or add a second helper specialized for Fn(&str) -> &str/borrowed results so trim can remain allocation-minimal.

Suggested change
unary_text_op("trim", args, |s| s.trim().to_string())
check_arg_count("trim", &args, 1)?;
let text = expect_text(&args[0])?;
let trimmed = text.trim();
Ok(Value::Text(Arc::from(trimmed)))

Copilot uses AI. Check for mistakes.
Comment thread src/stdlib/helpers.rs
Comment on lines +491 to +493
check_arg_count(func_name, &args, 1)?;
let text = expect_text(&args[0])?;
Ok(Value::Text(Arc::from(op(&text))))

Copilot AI Feb 17, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These calls rely on deref coercions from &Arc<str> to &str (op(&text) / op(&a, &b)), which is valid but a bit opaque. For readability and to make the intended types explicit, prefer passing text.as_ref() (and a.as_ref(), b.as_ref()) into the closures.

Copilot uses AI. Check for mistakes.
Comment thread src/stdlib/helpers.rs
Comment on lines +514 to +517
check_arg_count(func_name, &args, 2)?;
let a = expect_text(&args[0])?;
let b = expect_text(&args[1])?;
Ok(Value::Bool(op(&a, &b)))

Copilot AI Feb 17, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These calls rely on deref coercions from &Arc<str> to &str (op(&text) / op(&a, &b)), which is valid but a bit opaque. For readability and to make the intended types explicit, prefer passing text.as_ref() (and a.as_ref(), b.as_ref()) into the closures.

Copilot uses AI. Check for mistakes.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/stdlib/text.rs (1)

131-133: Nit: trim incurs an extra allocation via .to_string().

s.trim() returns a &str (a borrowed slice of the original), so .to_string() copies the data into a new String even when there's no leading/trailing whitespace. This is the conscious trade-off noted in the PR description and is fine for maintainability — just flagging for awareness.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/stdlib/text.rs` around lines 131 - 133, The current native_trim uses
s.trim().to_string(), which always allocates; change native_trim (and the
closure passed to unary_text_op) to check whether s.trim() is equal to s and
only allocate when different—return the original owned string/Value when
unchanged to avoid an unnecessary allocation, otherwise return
s.trim().to_string(); reference native_trim and the closure passed into
unary_text_op to locate the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/stdlib/text.rs`:
- Around line 131-133: The current native_trim uses s.trim().to_string(), which
always allocates; change native_trim (and the closure passed to unary_text_op)
to check whether s.trim() is equal to s and only allocate when different—return
the original owned string/Value when unchanged to avoid an unnecessary
allocation, otherwise return s.trim().to_string(); reference native_trim and the
closure passed into unary_text_op to locate the change.

@logbie logbie closed this Feb 20, 2026
@logbie
logbie deleted the jules-refactor-text-stdlib-helpers-10726499022893340770 branch February 20, 2026 07:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants